﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Lua4Net
{
    public class LuaTable : IDisposable
    {
        private string      _name;
        private int         _reference;
        private IntPtr      _l;
        private LuaTableOperation _op;

        public LuaTable(IntPtr l,string name, int index)
        {
            _l = l;
            _name = name;
            LuaApi.lua_pushvalue(l, index);
            _reference = LuaApi.lua_ref(l, -1);
            _op = new LuaTableOperation(l);
        }

        public void Dispose()
        {
            if (_l != IntPtr.Zero && _reference != 0)
            {
                LuaApi.lua_unref(_l, _reference);
                _reference = 0;
            }
        }

        public void Execute(Action<LuaTableOperation> OnGetTable)
        {
            int top = LuaApi.lua_gettop(_l);
            LuaApi.lua_getref(_l, _reference);
            _op._index = top+1;
            if (LuaApi.lua_type(_l, -1) == LuaType.LUA_TTABLE)
            {
                OnGetTable(_op);
            }
            else
            {
                OnGetTable(null);
            }
            LuaApi.lua_settop(_l, top);
        }

        public class LuaTableOperation
        {
            public  int         _index;
            private IntPtr      _l;

            public LuaTableOperation(IntPtr l)
            {
                _l = l;
            }

            public LuaType GetType(string name)
            {
                LuaApi.lua_pushstring(_l,name);
                return LuaApi.lua_type(_l, _index);
            }

            public int GetInt(string name)
            {
                LuaApi.lua_getfield(_l, _index, name);
                return LuaApi.lua_type(_l, -1) == LuaType.LUA_TNUMBER?(int)LuaApi.lua_tonumber(_l, -1):0;
            }

            public bool GetBoolean(string name)
            {
                return GetInt(name) != 0;
            }

            public string GetString(string name)
            {
                LuaApi.lua_getfield(_l, _index, name);
                return LuaApi.lua_type(_l, -1) == LuaType.LUA_TSTRING ? LuaApi.lua_tostring(_l, -1) : string.Empty;
            }

            public LuaRefFunction GetFunction(string name)
            {
                LuaApi.lua_getfield(_l, _index, name);
                return LuaApi.lua_type(_l, -1) == LuaType.LUA_TFUNCTION ? new LuaRefFunction(-1, _l) : null;
            }

            public LuaTable GetTable(string name)
            {
                LuaApi.lua_pushstring(_l,name);
                LuaApi.lua_rawget(_l,_index);
                return LuaApi.lua_type(_l, -1) == LuaType.LUA_TTABLE ? new LuaTable(_l, name, -1) : null;
            }

            public void SetInt(string name, int value)
            {;
                LuaApi.lua_pushnumber(_l,value);
                LuaApi.lua_setfield(_l, _index, name);
            }

            public void SetBoolean(string name, bool value)
            {
                SetInt(name, value ? 1 : 0);
            }

            public void SetString(string name, string value)
            {
                LuaApi.lua_pushstring(_l, value);
                LuaApi.lua_setfield(_l, _index, name);
            }

            public void SetNil(string name)
            {
                LuaApi.lua_pushnil(_l);
                LuaApi.lua_setfield(_l, _index, name);
            }

            public LuaTable NewTable(string name)
            {
                LuaApi.lua_newtable(_l);
                LuaTable table = new LuaTable(_l, name, -1);
                LuaApi.lua_setfield(_l, _index, name);
                return table;
            }
        } 
    }
}
